from flask import Blueprint, request, jsonify, send_from_directory, make_response
from .models import User, Post, Comment
from functools import wraps
from . import db
import bcrypt
import jwt
from datetime import datetime, timedelta
import os


def admin_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        token = request.headers.get('Authorization')
        if not token:
            return jsonify({'message': 'Token is missing'}), 401

        try:
            data = jwt.decode(token.split()[1], os.getenv('SECRET_KEY', 'secret'), algorithms=['HS256'])
            user = User.query.get(data['user_id'])
            if not user or user.role != 'admin':
                return jsonify({'message': 'Admin access required'}), 403
        except:
            return jsonify({'message': 'Token is invalid'}), 401

        return f(*args, **kwargs)

    return decorated_function


main = Blueprint('main', __name__)


@main.route('/')
def index():
    token = request.cookies.get('token')
    if token:
        try:
            jwt.decode(token, os.getenv('SECRET_KEY', 'secret'), algorithms=['HS256'])
            return send_from_directory('templates', 'index.html')
        except:
            pass
    return send_from_directory('templates', 'login.html')


@main.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return send_from_directory('templates', 'login.html')

    try:
        # 验证请求数据
        data = request.get_json()
        if not data or 'password' not in data:
            return jsonify({
                'status': 'error',
                'code': 400,
                'message': 'Missing required fields'
            }), 400

        # 查询用户
        user = User.query.filter_by(username=data.get('username'), role='admin').first()
        if not user:
            return jsonify({
                'status': 'error',
                'code': 401,
                'message': 'Invalid credentials'
            }), 401

        # 验证密码
        if not bcrypt.checkpw(data['password'].encode('utf-8'), user.password.encode('utf-8')):
            return jsonify({
                'status': 'error',
                'code': 401,
                'message': 'Invalid credentials'
            }), 401

        # 生成token
        token = jwt.encode({
            'user_id': user.id,
            'exp': datetime.utcnow() + timedelta(hours=24)
        }, os.getenv('SECRET_KEY', 'secret'))

        response = make_response(jsonify({
            'status': 'success',
            'code': 200,
            'data': {
                'token': token,
                'user_id': user.id,
                'username': user.username,
                'role': user.role
            }
        }), 200)
        response.set_cookie('token', token, httponly=True, secure=True, samesite='Lax')
        return response

    except Exception as e:
        import traceback
        traceback.print_exc()
        return jsonify({
            'status': 'error',
            'code': 500,
            'message': 'Internal server error',
            'detail': str(e)
        }), 500


# 获取管理员信息
@main.route('/user', methods=['GET'])
def get_current_user():
    token = request.headers.get('Authorization')
    if not token:
        return jsonify({'message': 'Token is missing'}), 401

    try:
        data = jwt.decode(token.split()[1], os.getenv('SECRET_KEY', 'secret'), algorithms=['HS256'])
        user = User.query.filter_by(id=data['user_id'], role='admin').first()
        if not user:
            return jsonify({'message': 'Admin not found'}), 404

        return jsonify({
            'id': user.id,
            'username': user.username,
            'email': user.email,
            'role': user.role
        }), 200
    except:
        return jsonify({'message': 'Token is invalid'}), 401


# 获取所有帖子
@main.route('/posts', methods=['GET'])
def get_posts():
    # 获取查询参数
    search = request.args.get('search', '')
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 10, type=int)
    sort_by = request.args.get('sort_by', 'created_at')
    sort_order = request.args.get('sort_order', 'desc')

    # 构建基础查询
    query = Post.query.filter_by(status=True)

    # 添加搜索条件
    if search:
        query = query.filter(
            (Post.title.ilike(f'%{search}%')) |
            (Post.content.ilike(f'%{search}%'))
        )

    # 添加排序
    if sort_by in ['title', 'created_at']:
        order_column = getattr(Post, sort_by)
        if sort_order == 'desc':
            query = query.order_by(order_column.desc())
        else:
            query = query.order_by(order_column.asc())

    # 分页处理
    pagination = query.paginate(page=page, per_page=per_page, error_out=False)
    posts = pagination.items

    # 构建响应数据
    output = []
    for post in posts:
        post_data = {
            'id': post.id,
            'title': post.title,
            'content': post.content,
            'author': post.author.username,
            'created_at': post.created_at
        }
        output.append(post_data)

    return jsonify({
        'posts': output,
        'total': pagination.total,
        'pages': pagination.pages,
        'current_page': pagination.page
    }), 200


# 创建帖子
@main.route('/posts', methods=['POST'])
def create_post():
    token = request.headers.get('Authorization')
    if not token:
        return jsonify({'message': 'Token is missing'}), 401

    try:
        data = jwt.decode(token.split()[1], os.getenv('SECRET_KEY', 'secret'), algorithms=['HS256'])
        user = User.query.get(data['user_id'])
        if not user:
            return jsonify({'message': 'User not found'}), 404
    except:
        return jsonify({'message': 'Token is invalid'}), 401

    post_data = request.get_json()

    # 输入验证
    if not post_data.get('title') or not post_data.get('content'):
        return jsonify({'message': 'Title and content are required'}), 400

    if len(post_data['title']) > 100:
        return jsonify({'message': 'Title is too long (max 100 characters)'}), 400

    try:
        new_post = Post(
            title=post_data['title'],
            content=post_data['content'],
            user_id=user.id,
            status=True
        )

        db.session.add(new_post)
        db.session.commit()

        return jsonify({
            'message': 'Post created successfully',
            'post_id': new_post.id
        }), 201

    except Exception as e:
        db.session.rollback()
        return jsonify({'message': 'Failed to create post', 'error': str(e)}), 500


# 更新帖子
@main.route('/posts/<int:id>', methods=['PUT'])
def update_post(id):
    token = request.headers.get('Authorization')
    if not token:
        return jsonify({'message': 'Token is missing'}), 401

    try:
        data = jwt.decode(token.split()[1], os.getenv('SECRET_KEY', 'secret'), algorithms=['HS256'])
        user = User.query.get(data['user_id'])
        if not user:
            return jsonify({'message': 'User not found'}), 404
    except:
        return jsonify({'message': 'Token is invalid'}), 401

    post = Post.query.get(id)
    if not post:
        return jsonify({'message': 'Post not found'}), 404

    if post.user_id != user.id:
        return jsonify({'message': 'Not authorized to edit this post'}), 403

    post_data = request.get_json()
    post.title = post_data['title']
    post.content = post_data['content']
    db.session.commit()

    return jsonify({'message': 'Post updated successfully'}), 200


# 删除帖子
@main.route('/posts/<int:id>', methods=['DELETE'])
def delete_post(id):
    token = request.headers.get('Authorization')
    if not token:
        return jsonify({'message': 'Token is missing'}), 401

    try:
        data = jwt.decode(token.split()[1], os.getenv('SECRET_KEY', 'secret'), algorithms=['HS256'])
        user = User.query.get(data['user_id'])
        if not user:
            return jsonify({'message': 'User not found'}), 404
    except:
        return jsonify({'message': 'Token is invalid'}), 401

    post = Post.query.get(id)
    if not post:
        return jsonify({'message': 'Post not found'}), 404

    if post.user_id != user.id and user.role != 'admin':
        return jsonify({'message': 'Not authorized to delete this post'}), 403

    db.session.delete(post)
    db.session.commit()

    return jsonify({'message': 'Post deleted successfully'}), 200


# 添加评论
@main.route('/posts/<int:id>/comments', methods=['POST'])
def add_comment(id):
    token = request.headers.get('Authorization')
    if not token:
        return jsonify({'message': 'Token is missing'}), 401

    try:
        data = jwt.decode(token.split()[1], os.getenv('SECRET_KEY', 'secret'), algorithms=['HS256'])
        user = User.query.get(data['user_id'])
        if not user:
            return jsonify({'message': 'User not found'}), 404
    except:
        return jsonify({'message': 'Token is invalid'}), 401

    post = Post.query.get(id)
    if not post:
        return jsonify({'message': 'Post not found'}), 404

    comment_data = request.get_json()
    if not comment_data.get('content'):
        return jsonify({'message': 'Comment content is required'}), 400

    if len(comment_data['content']) > 500:
        return jsonify({'message': 'Comment is too long (max 500 characters)'}), 400

    new_comment = Comment(
        content=comment_data['content'],
        author_id=user.id,
        post_id=post.id,
        status=True
    )

    db.session.add(new_comment)
    db.session.commit()

    return jsonify({
        'message': 'Comment added successfully',
        'comment_id': new_comment.id,
        'content': new_comment.content,
        'created_at': new_comment.created_at
    }), 201


@main.route('/admin/posts', methods=['GET', 'POST'])
@admin_required
def admin_posts():
    if request.method == 'POST':
        post_data = request.get_json()

        # 输入验证
        if not post_data.get('title') or not post_data.get('content'):
            return jsonify({'message': 'Title and content are required'}), 400

        if len(post_data['title']) > 100:
            return jsonify({'message': 'Title is too long (max 100 characters)'}), 400

        try:
            token = request.headers.get('Authorization')
            data = jwt.decode(token.split()[1], os.getenv('SECRET_KEY', 'secret'), algorithms=['HS256'])
            user = User.query.get(data['user_id'])

            new_post = Post(
                title=post_data['title'],
                content=post_data['content'],
                user_id=user.id,
                status=True
            )

            db.session.add(new_post)
            db.session.commit()

            return jsonify({
                'message': 'Post created successfully',
                'post_id': new_post.id
            }), 201

        except Exception as e:
            db.session.rollback()
            return jsonify({'message': 'Failed to create post', 'error': str(e)}), 500

    # GET方法原有逻辑
    posts = Post.query.all()
    output = []

    for post in posts:
        post_data = {
            'id': post.id,
            'title': post.title,
            'content': post.content,
            'author': post.author.username,
            'created_at': post.created_at,
            'status': post.status
        }
        output.append(post_data)

    return jsonify({'posts': output}), 200
    posts = Post.query.all()
    output = []

    for post in posts:
        post_data = {
            'id': post.id,
            'title': post.title,
            'content': post.content,
            'author': post.author.username,
            'created_at': post.created_at,
            'status': post.status
        }
        output.append(post_data)

    return jsonify({'posts': output}), 200


@main.route('/admin/posts/<int:id>', methods=['DELETE'])
@admin_required
def admin_delete_post(id):
    post = Post.query.get(id)
    if not post:
        return jsonify({'message': 'Post not found'}), 404

    # 先删除关联的评论
    for comment in post.comments:
        db.session.delete(comment)

    db.session.delete(post)
    db.session.commit()
    return jsonify({'message': 'Post deleted successfully'}), 200

@main.route('/admin/posts/<int:id>/ban', methods=['PUT'])
@admin_required
def ban_post(id):
    post = Post.query.get(id)
    if not post:
        return jsonify({'message': 'Post not found'}), 404

    post.status = False
    db.session.commit()
    return jsonify({'message': 'Post banned successfully'}), 200


@main.route('/admin/posts/<int:id>/unban', methods=['PUT'])
@admin_required
def unban_post(id):
    post = Post.query.get(id)
    if not post:
        return jsonify({'message': 'Post not found'}), 404

    post.status = True
    db.session.commit()
    return jsonify({'message': 'Post unbanned successfully'}), 200


@main.route('/admin/users', methods=['GET'])
@admin_required
def get_all_users():
    users = User.query.all()
    output = []

    for user in users:
        user_data = {
            'id': user.id,
            'username': user.username,
            'email': user.email,
            'role': user.role,
            'status': user.status
        }
        output.append(user_data)

    return jsonify({'users': output}), 200


@main.route('/admin/users/<int:id>/ban', methods=['PUT'])
@admin_required
def ban_user(id):
    user = User.query.get(id)
    if not user:
        return jsonify({'message': 'User not found'}), 404

    user.status = False
    db.session.commit()
    return jsonify({'message': 'User banned successfully'}), 200


@main.route('/admin/users/<int:id>/unban', methods=['PUT'])
@admin_required
def unban_user(id):
    user = User.query.get(id)
    if not user:
        return jsonify({'message': 'User not found'}), 404

    user.status = True
    db.session.commit()
    return jsonify({'message': 'User unbanned successfully'}), 200

@main.route('/admin/users/<int:id>', methods=['PUT'])
@admin_required
def update_user(id):
    user = User.query.get(id)
    if not user:
        return jsonify({'message': 'User not found'}), 404

    user_data = request.get_json()
    if 'username' in user_data:
        user.username = user_data['username']
    if 'email' in user_data:
        user.email = user_data['email']
    if 'role' in user_data:
        user.role = user_data['role']

    db.session.commit()
    return jsonify({'message': 'User updated successfully'}), 200

@main.route('/admin/users', methods=['POST'])
@admin_required
def create_user():
    user_data = request.get_json()
    if not user_data.get('username') or not user_data.get('email') or not user_data.get('password'):
        return jsonify({'message': 'Username, email and password are required'}), 400

    try:
        hashed_password = bcrypt.hashpw(user_data['password'].encode('utf-8'), bcrypt.gensalt())
        new_user = User(
            username=user_data['username'],
            email=user_data['email'],
            password=hashed_password.decode('utf-8'),
            role=user_data.get('role', 'user'),
            status=True
        )

        db.session.add(new_user)
        db.session.commit()

        return jsonify({
            'message': 'User created successfully',
            'user_id': new_user.id
        }), 201
    except Exception as e:
        db.session.rollback()
        return jsonify({'message': 'Failed to create user', 'error': str(e)}), 500

@main.route('/admin/users/<int:id>', methods=['DELETE'])
@admin_required
def delete_user(id):
    user = User.query.get(id)
    if not user:
        return jsonify({'message': 'User not found'}), 404

    # 先删除用户的所有关联comments
    for comment in user.comments:
        db.session.delete(comment)

    # 再删除用户的所有关联posts
    for post in user.posts:
        db.session.delete(post)

    db.session.delete(user)
    db.session.commit()
    return jsonify({'message': 'User deleted successfully'}), 200
@main.route('/admin/comments', methods=['GET', 'POST'], strict_slashes=False)
@admin_required
def admin_comments():
    if request.method == 'POST':
        try:
            comment_data = request.get_json()
            if not comment_data:
                return jsonify({'message': 'Invalid JSON data'}), 400

            # 验证必填字段
            if not comment_data.get('content') or not comment_data.get('post_id'):
                return jsonify({'message': 'Content and post_id are required'}), 400

            if len(comment_data['content']) > 500:
                return jsonify({'message': 'Comment is too long (max 500 characters)'}), 400

            # 验证用户和帖子
            token = request.headers.get('Authorization')
            data = jwt.decode(token.split()[1], os.getenv('SECRET_KEY', 'secret'), algorithms=['HS256'])
            user = User.query.get(data['user_id'])
            post = Post.query.get(comment_data['post_id'])

            if not post:
                return jsonify({'message': 'Post not found'}), 404

            # 创建评论
            new_comment = Comment(
                content=comment_data['content'],
                user_id=user.id,
                post_id=comment_data['post_id'],
                status=True
            )

            db.session.add(new_comment)
            db.session.commit()

            return jsonify({
                'message': 'Comment created successfully',
                'comment_id': new_comment.id,
                'content': new_comment.content,
                'created_at': new_comment.created_at
            }), 201

        except jwt.ExpiredSignatureError:
            return jsonify({'message': 'Token has expired'}), 401
        except jwt.InvalidTokenError:
            return jsonify({'message': 'Invalid token'}), 401
        except Exception as e:
            db.session.rollback()
            print(f"Error creating comment: {str(e)}")
            return jsonify({
                'message': 'Failed to create comment',
                'error': str(e)
            }), 500

    # GET方法逻辑
    search = request.args.get('search', '')
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 10, type=int)
    status = request.args.get('status', None)

    # 使用join优化查询，确保关联帖子数据被加载
    query = db.session.query(Comment).join(Post)

    if status is not None:
        query = query.filter(Comment.status == (status.lower() == 'true'))

    if search:
        query = query.filter(Comment.content.ilike(f'%{search}%'))

    pagination = query.paginate(page=page, per_page=per_page, error_out=False)
    comments = pagination.items

    output = []
    for comment in comments:
        comment_data = {
            'id': comment.id,
            'content': comment.content,
            'author': comment.author.username,
            'post_id': comment.post_id,
            'post_title': comment.post.title if comment.post else '[已删除]',
            'created_at': comment.created_at,
            'status': comment.status
        }
        output.append(comment_data)

    return jsonify({
        'comments': output,
        'total': pagination.total,
        'pages': pagination.pages,
        'current_page': pagination.page
    }), 200

@main.route('/admin/comments/<int:id>', methods=['DELETE'])
@admin_required
def delete_comment(id):
    comment = Comment.query.get(id)
    if not comment:
        return jsonify({'message': 'Comment not found'}), 404

    db.session.delete(comment)
    db.session.commit()
    return jsonify({'message': 'Comment deleted successfully'}), 200

@main.route('/admin/comments/<int:id>/ban', methods=['PUT'])
@admin_required
def ban_comment(id):
    comment = Comment.query.get(id)
    if not comment:
        return jsonify({'message': 'Comment not found'}), 404

    if not comment.status:
        return jsonify({'message': 'Comment is already banned'}), 400

    comment.status = False
    db.session.commit()
    return jsonify({
        'message': 'Comment banned successfully',
        'comment_id': comment.id,
        'status': comment.status
    }), 200

@main.route('/admin/comments/<int:id>/unban', methods=['PUT'])
@admin_required
def unban_comment(id):
    comment = Comment.query.get(id)
    if not comment:
        return jsonify({'message': 'Comment not found'}), 404

    if comment.status:
        return jsonify({'message': 'Comment is already active'}), 400

    comment.status = True
    db.session.commit()
    return jsonify({
        'message': 'Comment unbanned successfully',
        'comment_id': comment.id,
        'status': comment.status
    }), 200
